/* parcer.c is part of VIP program
 * Written by J. Salvador Arias, 2010
 *      CONICET, INSUE, Instituto Miguel Lillo,
 *      Miguel Lillo 205, S.M. de Tucuman (4000)
 *      Tucuman, Argentina
 *      e-mail: jsalarias@csnat.unt.edu.ar
 *
 * VIP is a free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation and
 * Creative Commons.
 *
 * This file and the VIP program is distributed in the hope
 * that it will be useful, but WITHOUT ANY WARRANTY; without
 * even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * To view a copy of this license, visit
 * http://creativecommons.org/licenses/GPL/2.0/
 * or send a letter to
 * Creative Commons, 171 Second Street, Suite 300,
 * San Francisco, California, 94105, USA.
 */

#include "parser.h"
#include "inxml.h"
#include "biogeo.h"
#include "out.h"

static GString* tempParserString = NULL;
static INSTREAM* in = NULL;
static INSTREAM* cmdLine = NULL;

static PROGRESSSTRUCT* progBar = NULL;

static XMLPARSER xmlParser = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, XML_ERROR };

static SFLAG BasicOpen ();
static SFLAG FeedOpen ();
static SFLAG BasicEnd ();
static SFLAG BasicError ();

static SFLAG OpenVIPTag ();
static SFLAG EndVIPTag ();
static SFLAG OnVIPError ();

static SFLAG OpenFeedTag ();
static SFLAG EndFeedTag ();
static SFLAG OnFeedError ();

static SFLAG FeedDarwinTag ();
static SFLAG EndDarwinTag ();

static SFLAG FeedXYDFile ();
static SFLAG FeedTABTable ();

static void StartNuFeed ();
static void FinishUnRead ();

static SFLAG OpenVRXTag ();
static SFLAG EndVRXTag ();
static SFLAG OnVRXError ();
static void FinishVRXFile ();

void CleanNameList (GList* toClean);

static SFLAG IsXYDFile ();

static SFLAG ReadRealTuple (INSTREAM* from, SREAL* r1, SREAL* r2);

SFLAG ReadFile (gchar* name, PROGRESSSTRUCT* progress) {
 SFLAG toRet;

 toRet = FALSE;
 if (in == NULL)
   in = CreateInStream ();
 if (cmdLine == NULL)
   cmdLine = CreateInStream ();
 if (tempParserString == NULL)
   tempParserString = g_string_new (VOIDSTRING);
 SETREADINGMODE (ALL_LOWER);
 if (SetInStreamToFile (in, name) != TRUE) return FALSE;
 if (IsXMLFile (in) == FALSE) {
   errorMessage = g_strdup_printf ("\nFile %s format is unknown\n", name);
   OnError ();
   ResetInStream (in);
   return FALSE;
 }
 progBar = progress;
 progBar -> numBar1 = in -> len;
 progBar -> actBar1 = 0;
 xmlParser . OpenTag = BasicOpen;
 xmlParser . EndTag = BasicEnd;
 xmlParser . OnError = BasicError;
 xmlParser . tempParserString = tempParserString;
 xmlParser . in = in;
 toRet = ReadXMLFile (&xmlParser);
 ResetInStream (in);
 ResetInStream (cmdLine);
 xmlParser . OpenTag = NULL;
 xmlParser . EndTag = NULL;
 xmlParser . OnError = NULL;
 xmlParser . tempParserString = NULL;
 xmlParser . in = NULL;
 return toRet;
}

SFLAG FeedFile (gchar* name, PROGRESSSTRUCT* progress) {
 SFLAG toRet;

 toRet = FALSE;
 if (in == NULL)
   in = CreateInStream ();
 if (cmdLine == NULL)
   cmdLine = CreateInStream ();
 if (tempParserString == NULL)
   tempParserString = g_string_new (VOIDSTRING);
 SETREADINGMODE (ALL_LOWER);
 if (SetInStreamToFile (in, name) != TRUE) return FALSE;
 progBar = progress;
 progBar -> numBar1 = in -> len;
 progBar -> actBar1 = 0;
 if (IsXMLFile (in) == TRUE) {
   xmlParser . OpenTag = FeedOpen;
   xmlParser . EndTag = BasicEnd;
   xmlParser . OnError = BasicError;
   xmlParser . tempParserString = tempParserString;
   xmlParser . in = in;
   toRet = ReadXMLFile (&xmlParser);
   xmlParser . OpenTag = NULL;
   xmlParser . EndTag = NULL;
   xmlParser . OnError = NULL;
   xmlParser . tempParserString = NULL;
   xmlParser . in = NULL;
 }
 else if (IsXYDFile () == TRUE)
   toRet = FeedXYDFile ();
 else
   toRet = FeedTABTable ();
 if (toRet != FALSE)
   FinishUnRead ();
 else {
   ResetInStream (in);
   return FALSE;
 }
 ResetInStream (in);
 ResetInStream (cmdLine);
 return toRet;
}

SFLAG ReadResults (gchar* name, PROGRESSSTRUCT* progress) {
 SFLAG toRet;

 toRet = FALSE;
 if (in == NULL)
   in = CreateInStream ();
 if (cmdLine == NULL)
   cmdLine = CreateInStream ();
 if (tempParserString == NULL)
   tempParserString = g_string_new (VOIDSTRING);
 SETREADINGMODE (ALL_LOWER);
 if (SetInStreamToFile (in, name) != TRUE) return FALSE;
 if (IsXMLFile (in) == FALSE) {
   errorMessage = g_strdup_printf ("\nFile %s format is unknown\n", name);
   OnError ();
   ResetInStream (in);
   return FALSE;
 }
 progBar = progress;
 progBar -> numBar1 = in -> len;
 progBar -> actBar1 = 0;
 xmlParser . OpenTag = OpenVRXTag;
 xmlParser . EndTag = EndVRXTag;
 xmlParser . OnError = OnVRXError;
 xmlParser . tempParserString = tempParserString;
 xmlParser . in = in;
 toRet = ReadXMLFile (&xmlParser);
 if (toRet != FALSE)
   FinishVRXFile ();
 ResetInStream (in);
 ResetInStream (cmdLine);
 xmlParser . OpenTag = NULL;
 xmlParser . EndTag = NULL;
 xmlParser . OnError = NULL;
 xmlParser . tempParserString = NULL;
 xmlParser . in = NULL;
 return toRet;
}

SFLAG BasicOpen () {
 progBar -> actBar1 = in -> actPos;
 UpdateOnCalculus ();
 if ((!g_strcmp0 (tempParserString -> str, "vip")) || (!g_strcmp0 (tempParserString -> str, "document")) ||
     (!g_strcmp0 (tempParserString -> str, "phyloxml")) || (!g_strcmp0 (tempParserString -> str, "kml"))) {
   if (xmlParser . tokenState & XML_WITH_PARAMS) {
     if (SkipParams (in) == XML_AUTO_CLOSE) {
       RemoveFromTokenList (&xmlParser);
       return TRUE;
     }
   }
   xmlParser . OpenTag = OpenVIPTag;
   xmlParser . EndTag = EndVIPTag;
   xmlParser . OnError = OnVIPError;
   xmlParser . fileHeader = g_strdup (tempParserString -> str);
 }
 else
   return IgnoreOpenTag (&xmlParser);
 return TRUE;
}

SFLAG FeedOpen () {
 progBar -> actBar1 = in -> actPos;
 UpdateOnCalculus ();
 if ((!g_strcmp0 (tempParserString -> str, "vip")) || (!g_strcmp0 (tempParserString -> str, "document")) ||
     (!g_strcmp0 (tempParserString -> str, "kml"))) {
   if (xmlParser . tokenState & XML_WITH_PARAMS) {
     if (SkipParams (in) == XML_AUTO_CLOSE) {
       RemoveFromTokenList (&xmlParser);
       return TRUE;
     }
   }
   StartNuFeed ();
   xmlParser . OpenTag = OpenFeedTag;
   xmlParser . EndTag = EndFeedTag;
   xmlParser . OnError = OnFeedError;
   xmlParser . fileHeader = g_strdup (tempParserString -> str);
 }
 else if (!g_strcmp0 (tempParserString -> str, "gbifresponse")) {
   if (xmlParser . tokenState & XML_WITH_PARAMS) {
     if (SkipParams (in) == XML_AUTO_CLOSE) {
       RemoveFromTokenList (&xmlParser);
       return TRUE;
     }
   }
   StartNuFeed ();
   xmlParser . OpenTag = FeedDarwinTag;
   xmlParser . EndTag = EndDarwinTag;
   xmlParser . OnError = OnFeedError;
   xmlParser . fileHeader = g_strdup (tempParserString -> str);
 }
 else
   return IgnoreOpenTag (&xmlParser);
 return TRUE;
}

SFLAG BasicEnd () {
 return TRUE;
}

SFLAG BasicError () {
 return FALSE;
}

/* Data reading variables */

static GNode* actNode = NULL;
static GNode* anc = NULL;
static GNode* sibling = NULL;
static GList* firstTerm = NULL;
static GList* lastTerm = NULL;
static GList* actTerm = NULL;
static GList* firstGeo = NULL;
static GList* lastGeo = NULL;
static GEOREF* actGeo = NULL;
static PHYLOTREE* nuTree = NULL;
static PHYLONODE* node = NULL;
static TERMINAL* term = NULL;

static GList* unReadList = NULL;
static GString* termName = NULL;
static GString* outBuffer = NULL;

static SCOUNTER numGeo = 0;
static SCOUNTER nodeId = 1000000;
static SREAL incMin = 360.00;
static SREAL incMax = 0;
static SREAL azmMin = 360.00;
static SREAL azmMax = 0;

static SREAL addLon = 360.00;
static SREAL addLat = 360.00;

static gchar* recordName = NULL;
static gchar* collecName = NULL;
static gchar* catalogName = NULL;
static gchar* urlName = NULL;
static gchar* referenceName = NULL;
static gchar* identifierName = NULL;
static gchar* sampleName = NULL;
static gchar* collectorName = NULL;

/* Function reading */
static void StartNuTree ();
static void ResetTreeVars ();
static void FreeNames ();
static void CloseTree ();

SFLAG OpenVIPTag () {
 GString* paramName;
 GString* actToken;
 PHYLONODE* parent;
 SINTEGER tmpNum;
 SFLAG onMarkup;
 SREAL lon, lat;
 SINTEGER age;

 progBar -> actBar1 = in -> actPos;
 UpdateOnCalculus ();
 if ((!g_strcmp0 (tempParserString -> str, "tree")) || (!g_strcmp0 (tempParserString -> str, "phylogeny"))) {
   if (xmlParser . tokenState & XML_WITH_PARAMS) {
     if (SkipParams (in) == XML_AUTO_CLOSE) {
       RemoveFromTokenList (&xmlParser);
       return TRUE;
     }
   }
   if (nuTree == NULL)
     StartNuTree ();
   else {
     errorMessage = g_strdup_printf ("\nBad \'<%s>\' token\nFile %s, line %ld\n", tempParserString -> str, in -> name, in -> line);
     return FALSE;
   }
 }
 else if ((!g_strcmp0 (tempParserString -> str, "node")) || (!g_strcmp0 (tempParserString -> str, "folder")) ||
     (!g_strcmp0 (tempParserString -> str, "clade"))) {
   actToken = (GString*) xmlParser . tokenStack -> data;
   if (nuTree == NULL)
     StartNuTree ();
   paramName = g_string_new (VOIDSTRING);
   tmpNum = nodeId;
   while (xmlParser . tokenState & XML_WITH_PARAMS) {
     ReadXMLTokenParam (in, paramName, tempParserString, &xmlParser . tokenState);
     if (xmlParser . tokenState == XML_ERROR) {
       g_string_free (paramName, TRUE);
       errorMessage = g_strdup_printf ("\nBad \'<%s>\' token\nFile %s, line %ld\n", actToken -> str, in -> name, in -> line);
       return FALSE;
     }
     else if (xmlParser . tokenState == XML_AUTO_CLOSE) {
       g_string_free (paramName, TRUE);
       RemoveFromTokenList (&xmlParser);
       return TRUE;
     }
     if (!g_strcmp0 (paramName -> str, "id")) {
       SetInStreamToString (cmdLine, tempParserString);
       if (ReadInt (cmdLine, &tmpNum) == FALSE) {
         errorMessage = g_strdup_printf ("\nBad \'id\' parameter on \'<Node>\' token\nFile %s, line %ld\n", in -> name, in -> line);
         OnError ();
         tmpNum = nodeId;
       }
       if (xmlParser . tokenState & XML_WITH_PARAMS) {
         if (SkipParams (in) == XML_AUTO_CLOSE) {
           RemoveFromTokenList (&xmlParser);
           return TRUE;
         }
       }
       break;
     }
   }
   actNode = CreateNode (nuTree, anc, sibling, tmpNum);
   node = (PHYLONODE*) actNode -> data;
   g_ptr_array_add (nuTree -> nodeArray, actNode);
   if (nuTree -> root == NULL)
     nuTree -> root = actNode;
   else {
     parent = (PHYLONODE*) anc -> data;
     node -> nested = parent -> nested + 1;
   }
   anc = actNode;
   sibling = NULL;
   term = NULL;
   g_string_free (paramName, TRUE);
   ++ nodeId;
 }
 else if ((!g_strcmp0 (tempParserString -> str, "placemark")) || (!g_strcmp0 (tempParserString -> str, "point"))
                || (!g_strcmp0 (tempParserString -> str, "specimeninfo"))) {
   if (xmlParser . tokenState & XML_WITH_PARAMS) {
     if (SkipParams (in) == XML_AUTO_CLOSE) {
       RemoveFromTokenList (&xmlParser);
       return TRUE;
     }
   }
   if (term == NULL) {
     term = CreateTerminal (actNode);
     actTerm = InsertListElement (lastTerm, term);
     term -> list = actTerm;
     if (firstTerm == NULL)
       firstTerm = actTerm;
     lastTerm = actTerm;
     node -> term = term;
     FreeNames ();
   }
   actGeo = NULL;
   if ((!g_strcmp0 (tempParserString -> str, "placemark")) || (!g_strcmp0 (tempParserString -> str, "specimeninfo")))
     FreeNames ();
 }
 else if (!g_strcmp0 (tempParserString -> str, "coordinates")) {
   actToken = GetPrevToken (&xmlParser);
   if (actToken == NULL) {
     errorMessage = g_strdup_printf ("\nUnexpected \'<coordinates>\' token\nFile %s, line %ld\n", in -> name, in -> line);
     return FALSE;
   }
   if ((g_strcmp0 (actToken -> str, "point")) && (g_strcmp0 (actToken -> str, "placemark")) &&
       (g_strcmp0 (tempParserString -> str, "specimeninfo"))) {
     errorMessage = g_strdup_printf ("\nReading \'<coordinates>\', without <point>\nFile %s, line %ld\n", in -> name, in -> line);
     return FALSE;
   }
   if (actGeo != NULL) {
     errorMessage = g_strdup_printf ("\nUnexpected \'<coordinates>\' token\nFile %s, line %ld\n", in -> name, in -> line);
     return FALSE;
   }
   if (xmlParser . tokenState & XML_WITH_PARAMS) {
     if (SkipParams (in) == XML_AUTO_CLOSE) {
       RemoveFromTokenList (&xmlParser);
       return TRUE;
     }
   }
   ReadXMLContent (in, tempParserString, &xmlParser . tokenState);
   if (xmlParser . tokenState != XML_TOKEN_CONTENT) {
     errorMessage = g_strdup_printf ("\nBad \'<coordinates>\' token\nFile %s, line %ld\n", in -> name, in -> line);
     return FALSE;
   }
   SetInStreamToString (cmdLine, tempParserString);
   if (ReadRealTuple (cmdLine, &lon, &lat) == TRUE) {
     if ((lon > -180.00001) && (lon < 180.00001) && (lat > -90.00001) && (lat < 90.00001)) {
       lastGeo = CreateGeoRef (lastGeo, actTerm,  lon, lat);
       if (firstGeo == NULL)
         firstGeo = lastGeo;
       if (term -> firstGeo == NULL)
         term -> firstGeo = lastGeo;
       ++ term -> numGeo;
       ++ numGeo;
       actGeo = (GEOREF*) lastGeo -> data;
       if (actGeo -> inclination > incMax)
         incMax = actGeo -> inclination;
       if (actGeo -> inclination < incMin)
         incMin = actGeo -> inclination;
       if (actGeo -> azimuth > azmMax)
         azmMax = actGeo -> azimuth;
       if (actGeo -> azimuth < azmMin)
         azmMin = actGeo -> azimuth;
     }
     else {
       errorMessage = g_strdup_printf ("\nBad \'<coordinates>\' token\nFile %s, line %ld\n", in -> name, in -> line);
       OnError ();
       actGeo = NULL;
     }
   }
   else {
     errorMessage = g_strdup_printf ("\nBad \'<coordinates>\' token\nFile %s, line %ld\n", in -> name, in -> line);
     OnError ();
     actGeo = NULL;
   }
 }
 else if (!g_strcmp0 (tempParserString -> str, "name")) {
   actToken = GetPrevToken (&xmlParser);
   if (actToken == NULL) {
     errorMessage = g_strdup_printf ("\nUnexpected \'<name>\' token\nFile %s, line %ld\n", in -> name, in -> line);
     return FALSE;
   }
   onMarkup = 0;
   if ((!g_strcmp0 (actToken -> str, "tree")) || (!g_strcmp0 (actToken -> str, "phylogeny")))
     onMarkup = 1;
   else if ((!g_strcmp0 (actToken -> str, "node")) || (!g_strcmp0 (actToken -> str, "folder")) || (!g_strcmp0 (actToken -> str, "clade")))
     onMarkup = 2;
   else if ((!g_strcmp0 (actToken -> str, "placemark")) || (!g_strcmp0 (actToken -> str, "specimeninfo")))
     onMarkup = 4;
   else {
     IgnoreOpenTag (&xmlParser);
     return TRUE;
   }
   if (xmlParser . tokenState & XML_WITH_PARAMS) {
     if (SkipParams (in) == XML_AUTO_CLOSE) {
       RemoveFromTokenList (&xmlParser);
       return TRUE;
     }
   }
   ReadXMLContent (in, tempParserString, &xmlParser . tokenState);
   if (xmlParser . tokenState != XML_TOKEN_CONTENT) {
     errorMessage = g_strdup_printf ("\nBad \'<name>\' token: %s\nFile %s, line %ld\n", tempParserString -> str, in -> name, in -> line);
     OnError ();
     return TRUE;
   }
   if (onMarkup == 1) {
     if (nuTree -> name != NULL)
       g_free (nuTree -> name);
     nuTree -> name = g_strdup (tempParserString -> str);
   }
   else if (onMarkup == 2) {
     if (node -> name != NULL)
       g_free (node -> name);
     node -> name = g_strdup (tempParserString -> str);
   }
   else if (onMarkup == 4)
     recordName = AddSynonim (term, tempParserString -> str);
 }
 else if (!g_strcmp0 (tempParserString -> str, "synonym")) {
   actToken = GetPrevToken (&xmlParser);
   if (actToken == NULL) {
     errorMessage = g_strdup_printf ("\nUnexpected \'<synonym>\' token\nFile %s, line %ld\n", in -> name, in -> line);
     return FALSE;
   }
   if ((g_strcmp0 (actToken -> str, "node")) && (g_strcmp0 (actToken -> str, "folder")) && (g_strcmp0 (actToken -> str, "clade"))) {
     IgnoreOpenTag (&xmlParser);
     return TRUE;
   }
   if (xmlParser . tokenState & XML_WITH_PARAMS) {
     if (SkipParams (in) == XML_AUTO_CLOSE) {
       RemoveFromTokenList (&xmlParser);
       return TRUE;
     }
   }
   ReadXMLContent (in, tempParserString, &xmlParser . tokenState);
   if (xmlParser . tokenState != XML_TOKEN_CONTENT) {
     errorMessage = g_strdup_printf ("\nBad \'<synonym>\' token: %s\nFile %s, line %ld\n", tempParserString -> str, in -> name, in -> line);
     OnError ();
     return TRUE;
   }
   if (term == NULL) {
     term = CreateTerminal (actNode);
     actTerm = InsertListElement (lastTerm, term);
     term -> list = actTerm;
     if (firstTerm == NULL)
       firstTerm = actTerm;
     lastTerm = actTerm;
     node -> term = term;
     FreeNames ();
   }
   AddSynonim (term, tempParserString -> str);
 }
 else if (!g_strcmp0 (tempParserString -> str, "taxonomy")) {
   actToken = GetPrevToken (&xmlParser);
   if (actToken == NULL) {
     errorMessage = g_strdup_printf ("\nUnexpected \'<%s>\' token\nFile %s, line %ld\n", tempParserString -> str, in -> name, in -> line);
     return FALSE;
   }
   if ((g_strcmp0 (actToken -> str, "node")) && (g_strcmp0 (actToken -> str, "folder")) && (g_strcmp0 (actToken -> str, "clade"))) {
     IgnoreOpenTag (&xmlParser);
     return TRUE;
   }
   if (xmlParser . tokenState & XML_WITH_PARAMS) {
     if (SkipParams (in) == XML_AUTO_CLOSE) {
       RemoveFromTokenList (&xmlParser);
       return TRUE;
     }
   }
 }
 else if (!g_strcmp0 (tempParserString -> str, "scientific_name")) {
   actToken = GetPrevToken (&xmlParser);
   if (actToken == NULL) {
     errorMessage = g_strdup_printf ("\nUnexpected \'<%s>\' token\nFile %s, line %ld\n", tempParserString -> str, in -> name, in -> line);
     return FALSE;
   }
   if (g_strcmp0 (actToken -> str, "taxonomy")) {
     IgnoreOpenTag (&xmlParser);
     return TRUE;
   }
   if (xmlParser . tokenState & XML_WITH_PARAMS) {
     if (SkipParams (in) == XML_AUTO_CLOSE) {
       RemoveFromTokenList (&xmlParser);
       return TRUE;
     }
   }
   ReadXMLContent (in, tempParserString, &xmlParser . tokenState);
   if (xmlParser . tokenState != XML_TOKEN_CONTENT) {
     errorMessage = g_strdup_printf ("\nBad \'<scientific_name>\' token: %s\nFile %s, line %ld\n", tempParserString -> str,
                                     in -> name, in -> line);
     OnError ();
     return TRUE;
   }
   if (node -> name != NULL)
     g_free (node -> name);
   node -> name = g_strdup (tempParserString -> str);
 }
 else if (!g_strcmp0 (tempParserString -> str, "date")) {
   actToken = GetPrevToken (&xmlParser);
   if (actToken == NULL) {
     errorMessage = g_strdup_printf ("\nUnexpected \'<%s>\' token\nFile %s, line %ld\n", tempParserString -> str, in -> name, in -> line);
     return FALSE;
   }
   if ((g_strcmp0 (actToken -> str, "node")) && (g_strcmp0 (actToken -> str, "folder")) && (g_strcmp0 (actToken -> str, "clade"))) {
     IgnoreOpenTag (&xmlParser);
     return TRUE;
   }
   if (xmlParser . tokenState & XML_WITH_PARAMS) {
     if (SkipParams (in) == XML_AUTO_CLOSE) {
       RemoveFromTokenList (&xmlParser);
       return TRUE;
     }
   }
 }
 else if ((!g_strcmp0 (tempParserString -> str, "age")) || (!g_strcmp0 (tempParserString -> str, "date")) ||
          (!g_strcmp0 (tempParserString -> str, "minimum")) || (!g_strcmp0 (tempParserString -> str, "maximum"))) {
   actToken = GetPrevToken (&xmlParser);
   if (actToken == NULL) {
     errorMessage = g_strdup_printf ("\nUnexpected \'<%s>\' token\nFile %s, line %ld\n", tempParserString -> str, in -> name, in -> line);
     return FALSE;
   }
   if ((!g_strcmp0 (tempParserString -> str, "age")) || (g_strcmp0 (tempParserString -> str, "date"))) {
     if ((g_strcmp0 (actToken -> str, "node")) && (g_strcmp0 (actToken -> str, "folder")) && (g_strcmp0 (actToken -> str, "clade"))) {
       IgnoreOpenTag (&xmlParser);
       return TRUE;
     }
   }
   else if (!g_strcmp0 (tempParserString -> str, "minimum")) {
     if ((!g_strcmp0 (tempParserString -> str, "age")) || (g_strcmp0 (actToken -> str, "date"))) {
       IgnoreOpenTag (&xmlParser);
       return TRUE;
     }
   }
   if (xmlParser . tokenState & XML_WITH_PARAMS) {
     if (SkipParams (in) == XML_AUTO_CLOSE) {
       RemoveFromTokenList (&xmlParser);
       return TRUE;
     }
   }
   ReadXMLContent (in, tempParserString, &xmlParser . tokenState);
   if (xmlParser . tokenState != XML_TOKEN_CONTENT) {
     errorMessage = g_strdup_printf ("\nBad \'<age>\' token: %s\nFile %s, line %ld\n", tempParserString -> str, in -> name, in -> line);
     OnError ();
     return TRUE;
   }
   SetInStreamToString (cmdLine, tempParserString);
   ReadInt (cmdLine, &age);
   if (age >= 0)
     SetNodeAge (actNode, (SCOUNTER) age, TRUE);
 }
 else if ((!g_strcmp0 (tempParserString -> str, "lat")) || (!g_strcmp0 (tempParserString -> str, "long"))) {
   actToken = GetPrevToken (&xmlParser);
   if (actToken == NULL) {
     errorMessage = g_strdup_printf ("\nUnexpected \'<%s>\' token\nFile %s, line %ld\n", tempParserString -> str, in -> name, in -> line);
     return FALSE;
   }
   if (g_strcmp0 (actToken -> str, "point")) {
     IgnoreOpenTag (&xmlParser);
     return TRUE;
   }
   if (actGeo != NULL) {
     errorMessage = g_strdup_printf ("\nUnexpected \'<%s>\' token\nFile %s, line %ld\n", tempParserString -> str, in -> name, in -> line);
     return FALSE;
   }
   if (xmlParser . tokenState & XML_WITH_PARAMS) {
     if (SkipParams (in) == XML_AUTO_CLOSE) {
       RemoveFromTokenList (&xmlParser);
       return TRUE;
     }
   }
   onMarkup = 1;
   if (!g_strcmp0 (tempParserString -> str, "lat"))
     onMarkup = 2;
   ReadXMLContent (in, tempParserString, &xmlParser . tokenState);
   if (xmlParser . tokenState != XML_TOKEN_CONTENT) {
     errorMessage = g_strdup_printf ("\nBad \'<age>\' token: %s\nFile %s, line %ld\n", tempParserString -> str, in -> name, in -> line);
     OnError ();
     return TRUE;
   }
   SetInStreamToString (cmdLine, tempParserString);
   if (onMarkup == 1)
     ReadReal (cmdLine, &addLon);
   else
     ReadReal (cmdLine, &addLat);
 }
 else if ((!g_strcmp0 (tempParserString -> str, "collection")) || (!g_strcmp0 (tempParserString -> str, "catalogcode")) ||
          (!g_strcmp0 (tempParserString -> str, "url")) || (!g_strcmp0 (tempParserString -> str, "reference")) ||
          (!g_strcmp0 (tempParserString -> str, "identifiedby")) || (!g_strcmp0 (tempParserString -> str, "collectiondate")) ||
          (!g_strcmp0 (tempParserString -> str, "collector"))) {
   actToken = GetPrevToken (&xmlParser);
   if (actToken == NULL) {
     errorMessage = g_strdup_printf ("\nUnexpected \'<%s>\' token\nFile %s, line %ld\n", tempParserString -> str,
                                     in -> name, in -> line);
     return FALSE;
   }
   if ((g_strcmp0 (actToken -> str, "placemark")) && (g_strcmp0 (actToken -> str, "specimeninfo"))) {
     errorMessage = g_strdup_printf ("\nReading \'<%s>\', without <SpecimenInfo>\nFile %s, line %ld\n",
                                     tempParserString -> str, in -> name, in -> line);
     return FALSE;
   }
   if (xmlParser . tokenState & XML_WITH_PARAMS) {
     if (SkipParams (in) == XML_AUTO_CLOSE) {
       RemoveFromTokenList (&xmlParser);
       return TRUE;
     }
   }
   actToken = xmlParser . tokenStack -> data;
   ReadXMLContent (in, tempParserString, &xmlParser . tokenState);
   if (xmlParser . tokenState == XML_TOKEN_NOCONTENT) return TRUE;
   if (xmlParser . tokenState != XML_TOKEN_CONTENT) {
     errorMessage = g_strdup_printf ("\nBad \'<%s>\' token\nFile %s, line %ld\n", actToken -> str, in -> name, in -> line);
     return FALSE;
   }
   if (!g_strcmp0 (actToken -> str, "collection"))
     collecName = g_strdup (tempParserString -> str);
   else if (!g_strcmp0 (actToken -> str, "catalogcode"))
     catalogName = g_strdup (tempParserString -> str);
   else if (!g_strcmp0 (actToken -> str, "url"))
     urlName = g_strdup (tempParserString -> str);
   else if (!g_strcmp0 (actToken -> str, "reference"))
     referenceName = g_strdup (tempParserString -> str);
   else if (!g_strcmp0 (actToken -> str, "identifiedby"))
     identifierName = g_strdup (tempParserString -> str);
   else if (!g_strcmp0 (actToken -> str, "collectiondate"))
     sampleName = g_strdup (tempParserString -> str);
   else if (!g_strcmp0 (actToken -> str, "collector"))
     collectorName = g_strdup (tempParserString -> str);
 }
 else
   return IgnoreOpenTag (&xmlParser);
 return TRUE;
}

SFLAG EndVIPTag () {
 GString* actToken;
 PHYLONODE* parent;
 SINTEGER tmpNum;

 actToken = (GString*) xmlParser . tokenStack -> data;
 if (!g_strcmp0 (tempParserString -> str, "tree"))
   nuTree = NULL;
 else if ((!g_strcmp0 (tempParserString -> str, "node")) || (!g_strcmp0 (tempParserString -> str, "folder"))
           || (!g_strcmp0 (tempParserString -> str, "clade"))) {
   tmpNum = g_node_n_children (actNode);
   if (tmpNum == 1) {
     errorMessage = g_strdup_printf ("\nFewer than 2 descendants in a node\nFile %s, line %ld\n", in -> name, in -> line);
     return FALSE;
   }
   else if ((tmpNum != 0) && (node -> term != NULL)) {
     errorMessage = g_strdup_printf ("\nTerminals must be without descendants\nFile %s, line %ld\n", in -> name, in -> line);
     return FALSE;
   }
   else if (tmpNum == 0) {
     node -> level = 1;
     node -> numTerms = 1;
     node -> size = 1;
     if (node -> minAge == NO_AGE)
       node -> minAge = 0;
     if (term == NULL) {
       term = CreateTerminal (actNode);
       actTerm = InsertListElement (lastTerm, term);
       term -> list = actTerm;
       if (firstTerm == NULL)
         firstTerm = actTerm;
       lastTerm = actTerm;
       node -> term = term;
     }
     if (node -> name != NULL)
       term -> name = AddSynonim (term, node -> name);
     UpdateWithData (term);
   }
   anc = actNode -> parent;
   if (anc != NULL) {
     parent = (PHYLONODE*) anc -> data;
     parent -> numTerms += node -> numTerms;
     parent -> size += node -> size;
     if (node -> level >= parent -> level)
       parent -> level = node -> level + 1;
     /* Update the actual node */
     sibling = actNode;
     actNode = anc;
     node = (PHYLONODE*) actNode -> data;
   }
   else
     CloseTree ();
 }
 else if (!g_strcmp0 (tempParserString -> str, "point")) {
   if (actGeo == NULL) {
     if ((addLon > -180.00001) && (addLon < 180.00001) && (addLat > -90.00001) && (addLat < 90.00001)) {
       if (term != NULL) {
         lastGeo = CreateGeoRef (lastGeo, actTerm,  addLon, addLat);
         if (firstGeo == NULL)
           firstGeo = lastGeo;
         if (term -> firstGeo == NULL)
           term -> firstGeo = lastGeo;
         ++ term -> numGeo;
         ++ numGeo;
         actGeo = (GEOREF*) lastGeo -> data;
         if (actGeo -> inclination > incMax)
           incMax = actGeo -> inclination;
         if (actGeo -> inclination < incMin)
           incMin = actGeo -> inclination;
         if (actGeo -> azimuth > azmMax)
           azmMax = actGeo -> azimuth;
         if (actGeo -> azimuth < azmMin)
           azmMin = actGeo -> azimuth;
       }
       actGeo = NULL;
       addLon = 360.00;
       addLat = 360.00;
     }
   }
 }
 else if ((!g_strcmp0 (tempParserString -> str, "placemark")) || (!g_strcmp0 (tempParserString -> str, "specimeninfo"))) {
   if (actGeo != NULL) {
     actGeo -> name = recordName;
     actGeo -> collec = collecName;
     actGeo -> catalog = catalogName;
     actGeo -> url = urlName;
     actGeo -> reference = referenceName;
     actGeo -> identifier = identifierName;
     actGeo -> sampleDate = sampleName;
     actGeo -> collector = collectorName;
     recordName = NULL;
     collecName = NULL;
     catalogName = NULL;
     urlName = NULL;
     referenceName = NULL;
     identifierName = NULL;
     sampleName = NULL;
     collectorName = NULL;
   }
   else
     FreeNames ();
   actGeo = NULL;
 }
 return TRUE;
}

SFLAG OnVIPError () {
 OnError ();
 DestroyTree (nuTree);
 DestroyTermList (firstTerm);
 DestroyGeoList (firstGeo);
 if (GETLASTSPP == NULL)
   SETSPP (NULL);
 if (GETLASTGEOREF == NULL)
   SETGEOREF (NULL);
 FreeNames ();
 nuTree = NULL;
 return FALSE;
}

void StartNuTree () {
 ResetTreeVars ();
 lastTerm = GETLASTSPP;
 lastGeo = GETLASTGEOREF;
 actGeo = NULL;
 incMin = GETMININC;
 incMax = GETMAXINC;
 azmMin = GETMINAZM;
 azmMax = GETMAXAZM;
 nuTree = CreateTree (NULL, GETNUMTREES);
}

void ResetTreeVars () {
 actNode = anc = sibling = NULL;
 firstTerm = NULL;
 firstGeo = NULL;
 actGeo = NULL;
 numGeo = 0;
 node = NULL;
 term = NULL;
 actTerm = NULL;
 nodeId = g_random_int_range (1000000, 9999999);
 FreeNames ();
}

void CloseTree () {
 GString* actToken;

 if (nuTree == NULL) return;
 if (nuTree -> root == NULL) {
   DestroyTree (nuTree);
   return;
 }
 PrepareTree (nuTree);
 nuTree -> list = InsertListElement (GETLASTTREE, nuTree);
 if (GETTREES == NULL)
   SETTREES (nuTree -> list);
 SETLASTTREE (nuTree -> list);
 INCREASENUMTREES (1);
 if (GETSPP == NULL)
   SETSPP (firstTerm);
 SETLASTSPP (lastTerm);
 node = (PHYLONODE*) nuTree -> root -> data;
 INCREASENUMSPP (node -> numTerms);
 if (GETGEOREF == NULL)
   SETGEOREF (firstGeo);
 SETLASTGEOREF (lastGeo);
 INCREASENUMGEOREFS (numGeo);
 if (GETMAXAZM < azmMax)
   SETMAXAZM (azmMax);
 if (GETMINAZM > azmMin)
   SETMINAZM (azmMin);
 if (GETMAXINC < incMax)
   SETMAXINC (incMax);
 if (GETMININC > incMin)
   SETMININC (incMin);
 node = (PHYLONODE*) nuTree -> root -> data;
 ResetTreeVars ();
 actToken = GetPrevToken (&xmlParser);
 if (g_strcmp0 (tempParserString -> str, "tree"))
   nuTree = NULL;
}

SFLAG OpenFeedTag () {
 SFLAG onMarkup;
 GString* actToken;

 progBar -> actBar1 = in -> actPos;
 UpdateOnCalculus ();
 if (!g_strcmp0 (tempParserString -> str, "name")) {
   actToken = GetPrevToken (&xmlParser);
   if (actToken == NULL) {
     errorMessage = g_strdup_printf ("\nUnexpected \'<name>\' token\nFile %s, line %ld\n", in -> name, in -> line);
     return FALSE;
   }
   onMarkup = 0;
   if ((!g_strcmp0 (actToken -> str, "node")) || (!g_strcmp0 (actToken -> str, "folder")) || (!g_strcmp0 (actToken -> str, "clade")))
     onMarkup = 2;
   else if ((!g_strcmp0 (actToken -> str, "placemark")) || (!g_strcmp0 (actToken -> str, "point"))
             || (!g_strcmp0 (actToken -> str, "specimeninfo")))
     onMarkup = 4;
   else {
     IgnoreOpenTag (&xmlParser);
     return TRUE;
   }
   if (xmlParser . tokenState & XML_WITH_PARAMS) {
     if (SkipParams (in) == XML_AUTO_CLOSE) {
       RemoveFromTokenList (&xmlParser);
       return TRUE;
     }
   }
   ReadXMLContent (in, tempParserString, &xmlParser . tokenState);
   if (xmlParser . tokenState != XML_TOKEN_CONTENT) {
     errorMessage = g_strdup_printf ("\nBad \'<name>\' token: %s\nFile %s, line %ld\n", tempParserString -> str, in -> name, in -> line);
     OnError ();
     return TRUE;
   }
   if (onMarkup == 2) {
     term = GetTermFromName (tempParserString -> str);
     if (termName != NULL)
       g_string_free (termName, TRUE);
     termName = g_string_new (tempParserString -> str);
   }
   else if (onMarkup == 4) {
     if (term != NULL)
       recordName = AddSynonim (term, tempParserString -> str);
     else {
       if (termName != NULL)
         g_string_free (termName, TRUE);
       termName = g_string_new (tempParserString -> str);
     }
   }
 }
 else if (!g_strcmp0 (tempParserString -> str, "synonym")) {
   actToken = GetPrevToken (&xmlParser);
   if (actToken == NULL) {
     errorMessage = g_strdup_printf ("\nUnexpected \'<synonym>\' token\nFile %s, line %ld\n", in -> name, in -> line);
     return FALSE;
   }
   if ((g_strcmp0 (actToken -> str, "node")) && (g_strcmp0 (actToken -> str, "folder")) && (g_strcmp0 (actToken -> str, "clade"))) {
     IgnoreOpenTag (&xmlParser);
     return TRUE;
   }
   if (xmlParser . tokenState & XML_WITH_PARAMS) {
     if (SkipParams (in) == XML_AUTO_CLOSE) {
       RemoveFromTokenList (&xmlParser);
       return TRUE;
     }
   }
   ReadXMLContent (in, tempParserString, &xmlParser . tokenState);
   if (xmlParser . tokenState != XML_TOKEN_CONTENT) {
     errorMessage = g_strdup_printf ("\nBad \'<synonym>\' token\nFile %s, line %ld\n", in -> name, in -> line);
     OnError ();
     return TRUE;
   }
   if (term != NULL)
     AddSynonim (term, tempParserString -> str);
 }
 else if (!g_strcmp0 (tempParserString -> str, "coordinates")) {
   actToken = GetPrevToken (&xmlParser);
   if (actToken == NULL) {
     errorMessage = g_strdup_printf ("\nUnexpected \'<coordinates>\' token\nFile %s, line %ld\n", in -> name, in -> line);
     return FALSE;
   }
   if ((g_strcmp0 (actToken -> str, "point")) && (g_strcmp0 (actToken -> str, "placemark")) &&
       (g_strcmp0 (tempParserString -> str, "specimeninfo"))) {
     errorMessage = g_strdup_printf ("\nReading \'<coordinates>\', without <point>\nFile %s, line %ld\n", in -> name, in -> line);
     return FALSE;
   }
   if (actGeo != NULL) {
     errorMessage = g_strdup_printf ("\nUnexpected \'<coordinates>\' token\nFile %s, line %ld\n", in -> name, in -> line);
     return FALSE;
   }
   if (xmlParser . tokenState & XML_WITH_PARAMS) {
     if (SkipParams (in) == XML_AUTO_CLOSE) {
       RemoveFromTokenList (&xmlParser);
       return TRUE;
     }
   }
   ReadXMLContent (in, tempParserString, &xmlParser . tokenState);
   if (xmlParser . tokenState != XML_TOKEN_CONTENT) {
     errorMessage = g_strdup_printf ("\nBad \'<coordinates>\' token\nFile %s, line %ld\n", in -> name, in -> line);
     return FALSE;
   }
   SetInStreamToString (cmdLine, tempParserString);
   if (ReadRealTuple (cmdLine, &addLon, &addLat) == TRUE) {
     if ((addLon > -180.00001) && (addLon < 180.00001) && (addLat > -90.00001) && (addLat < 90.00001)) {
       if (term != NULL)
         actGeo = AddGeoRef (addLon, addLat, term -> node);
       else
         actGeo = NULL;
     }
     else {
       errorMessage = g_strdup_printf ("\nBad \'<coordinates>\' token\nFile %s, line %ld\n", in -> name, in -> line);
       OnError ();
       actGeo = NULL;
     }
   }
   else {
     errorMessage = g_strdup_printf ("\nBad \'<coordinates>\' token\nFile %s, line %ld\n", in -> name, in -> line);
     OnError ();
     actGeo = NULL;
   }
 }
 else if ((!g_strcmp0 (tempParserString -> str, "collection")) || (!g_strcmp0 (tempParserString -> str, "catalogcode")) ||
          (!g_strcmp0 (tempParserString -> str, "url")) || (!g_strcmp0 (tempParserString -> str, "reference")) ||
          (!g_strcmp0 (tempParserString -> str, "identifiedby")) || (!g_strcmp0 (tempParserString -> str, "collectiondate")) ||
          (!g_strcmp0 (tempParserString -> str, "collector"))) {
   actToken = GetPrevToken (&xmlParser);
   if (actToken == NULL) {
     errorMessage = g_strdup_printf ("\nUnexpected \'<%s>\' token\nFile %s, line %ld\n", tempParserString -> str,
                                     in -> name, in -> line);
     return FALSE;
   }
   if ((g_strcmp0 (actToken -> str, "placemark")) && (g_strcmp0 (actToken -> str, "specimeninfo"))) {
     errorMessage = g_strdup_printf ("\nReading \'<%s>\', without <SpecimenInfo>\nFile %s, line %ld\n",
                                     tempParserString -> str, in -> name, in -> line);
     return FALSE;
   }
   if (xmlParser . tokenState & XML_WITH_PARAMS) {
     if (SkipParams (in) == XML_AUTO_CLOSE) {
       RemoveFromTokenList (&xmlParser);
       return TRUE;
     }
   }
   actToken = xmlParser . tokenStack -> data;
   ReadXMLContent (in, tempParserString, &xmlParser . tokenState);
   if (xmlParser . tokenState == XML_TOKEN_NOCONTENT) return TRUE;
   if (xmlParser . tokenState != XML_TOKEN_CONTENT) {
     errorMessage = g_strdup_printf ("\nBad \'<%s>\' token\nFile %s, line %ld\n", actToken -> str, in -> name, in -> line);
     return FALSE;
   }
   if (!g_strcmp0 (actToken -> str, "collection"))
     collecName = g_strdup (tempParserString -> str);
   else if (!g_strcmp0 (actToken -> str, "catalogcode"))
     catalogName = g_strdup (tempParserString -> str);
   else if (!g_strcmp0 (actToken -> str, "url"))
     urlName = g_strdup (tempParserString -> str);
   else if (!g_strcmp0 (actToken -> str, "reference"))
     referenceName = g_strdup (tempParserString -> str);
   else if (!g_strcmp0 (actToken -> str, "identifiedby"))
     identifierName = g_strdup (tempParserString -> str);
   else if (!g_strcmp0 (actToken -> str, "collectiondate"))
     sampleName = g_strdup (tempParserString -> str);
   else if (!g_strcmp0 (actToken -> str, "collector"))
     collectorName = g_strdup (tempParserString -> str);
 }
 else
   return IgnoreOpenTag (&xmlParser);
 return TRUE;
}

SFLAG EndFeedTag () {
 GString* actToken;
 gchar* numStr;

 actToken = (GString*) xmlParser . tokenStack -> data;
 if ((!g_strcmp0 (tempParserString -> str, "placemark")) || (!g_strcmp0 (tempParserString -> str, "specimeninfo"))) {
   if (actGeo != NULL) {
     actGeo -> name = recordName;
     actGeo -> collec = collecName;
     actGeo -> catalog = catalogName;
     actGeo -> url = urlName;
     actGeo -> reference = referenceName;
     actGeo -> identifier = identifierName;
     actGeo -> sampleDate = sampleName;
     actGeo -> collector = collectorName;
     recordName = NULL;
     collecName = NULL;
     catalogName = NULL;
     urlName = NULL;
     referenceName = NULL;
     identifierName = NULL;
     sampleName = NULL;
     collectorName = NULL;
   }
   else {
     if ((addLon > -180.00001) && (addLon < 180.00001) && (addLat > -90.00001) && (addLat < 90.00001) && (termName != NULL)) {
       g_string_append_printf (outBuffer, "\n<Folder>");
       g_string_append_printf (outBuffer, "\n\t<name>%s</name>", termName -> str);
       g_string_append (outBuffer, "\n\t<SpecimenInfo>");
       if (recordName != NULL) {
         g_string_append_printf (outBuffer,"\n\t\t<name>%s</name>", recordName);
         g_free (recordName);
       }
       if (collecName != NULL)
         g_string_append_printf (outBuffer, "\n\t\t<collection>%s</collection>", collecName);
       if (catalogName != NULL)
         g_string_append_printf (outBuffer, "\n\t\t<catalogCode>%s</catalogCode>", catalogName);
       if (urlName != NULL)
         g_string_append_printf (outBuffer, "\n\t\t<url>%s</url>", urlName);
       if (referenceName != NULL)
         g_string_append_printf (outBuffer, "\n\t\t<reference>%s</reference>", referenceName);
       if (identifierName != NULL)
         g_string_append_printf (outBuffer, "\n\t\t<identifiedBy>%s</identifiedBy>", identifierName);
       if (sampleName != NULL)
         g_string_append_printf (outBuffer, "\n\t\t<collectionDate>%s</collectionDate>", sampleName);
       if (collectorName != NULL)
         g_string_append_printf (outBuffer, "\n\t\t<collector>%s</collector>", collectorName);
       g_string_append (outBuffer, "\n\t\t<Point>");
       g_string_append (outBuffer, "\n\t\t\t<coordinates>");
       numStr = g_strdup_printf ("%.6f", addLon);
       CheckRealStr (numStr);
       g_string_append_printf (outBuffer, "%s,", numStr);
       g_free (numStr);
       numStr = g_strdup_printf ("%.6f", addLat);
       CheckRealStr (numStr);
       g_string_append (outBuffer, numStr);
       g_free (numStr);
       g_string_append (outBuffer, "</coordinates>");
       g_string_append (outBuffer, "\n\t\t</Point>\n\t</SpecimenInfo>");
       g_string_append (outBuffer, "\n</Folder>");
       unReadList = NameOnList (termName -> str, unReadList);
     }
     FreeNames ();
   }
   actGeo = NULL;
   addLat = 360.00;
   addLon = 360.00;
 }
 else if ((!g_strcmp0 (tempParserString -> str, "node")) || (!g_strcmp0 (tempParserString -> str, "folder"))
           || (!g_strcmp0 (tempParserString -> str, "clade"))) {
   term = NULL;
   if (termName != NULL)
     g_string_free (termName, TRUE);
   termName = NULL;
   actGeo = NULL;
 }
 return TRUE;
}

SFLAG OnFeedError () {
 OnError ();
 FinishUnRead ();
 FreeNames ();
 return FALSE;
}

SFLAG FeedDarwinTag () {
 GString* actToken;
 GString* paramName;
 SREAL tmp;

 progBar -> actBar1 = in -> actPos;
 UpdateOnCalculus ();
 if (!g_strcmp0 (tempParserString -> str, "tax:taxonoccurrence")) {
   actToken = (GString*) xmlParser . tokenStack -> data;
   paramName = g_string_new (VOIDSTRING);
   while (xmlParser . tokenState & XML_WITH_PARAMS) {
     ReadXMLTokenParam (in, paramName, tempParserString, &xmlParser . tokenState);
     if (xmlParser . tokenState == XML_ERROR) {
       g_string_free (paramName, TRUE);
       errorMessage = g_strdup_printf ("\nBad \'<%s>\' token\nFile %s, line %ld\n", actToken -> str, in -> name, in -> line);
       return FALSE;
     }
     else if (xmlParser . tokenState == XML_AUTO_CLOSE) {
       g_string_free (paramName, TRUE);
       RemoveFromTokenList (&xmlParser);
       return TRUE;
     }
     if (!g_strcmp0 (paramName -> str, "rdf:about")) {
       urlName = g_strdup (tempParserString -> str);
       if (xmlParser . tokenState & XML_WITH_PARAMS) {
         if (SkipParams (in) == XML_AUTO_CLOSE) {
           RemoveFromTokenList (&xmlParser);
           return TRUE;
         }
       }
       break;
     }
   }
   term = NULL;
   if (termName != NULL)
     g_string_free (termName, TRUE);
   termName = NULL;
   actGeo = NULL;
   addLon = 360.00;
   addLat = 360.00;
 }
 else if (!g_strcmp0 (tempParserString -> str, "name")) {
   actToken = GetPrevToken (&xmlParser);
   if (actToken == NULL) {
     errorMessage = g_strdup_printf ("\nUnexpected \'<name>\' token\nFile %s, line %ld\n", in -> name, in -> line);
     return FALSE;
   }
   if (g_strcmp0 (actToken -> str, "dataresource")) {
     IgnoreOpenTag (&xmlParser);
     return TRUE;
   }
   if (xmlParser . tokenState & XML_WITH_PARAMS) {
     if (SkipParams (in) == XML_AUTO_CLOSE) {
       RemoveFromTokenList (&xmlParser);
       return TRUE;
     }
   }
   ReadXMLContent (in, tempParserString, &xmlParser . tokenState);
   if (xmlParser . tokenState != XML_TOKEN_CONTENT) {
     errorMessage = g_strdup_printf ("\nBad \'<name>\' token: %s\nFile %s, line %ld\n", tempParserString -> str, in -> name, in -> line);
     OnError ();
     return TRUE;
   }
   collecName = g_strdup (tempParserString -> str);
 }
 else if (!g_strcmp0 (tempParserString -> str, "tax:catalognumber")) {
   actToken = GetPrevToken (&xmlParser);
   if (actToken == NULL) {
     errorMessage = g_strdup_printf ("\nUnexpected \'<%s>\' token\nFile %s, line %ld\n", tempParserString -> str, in -> name, in -> line);
     return FALSE;
   }
   if (g_strcmp0 (actToken -> str, "tax:taxonoccurrence")) {
     errorMessage = g_strdup_printf ("\nUnexpected \'<%s>\' token\nFile %s, line %ld\n", tempParserString -> str, in -> name, in -> line);
     return FALSE;
   }
   if (xmlParser . tokenState & XML_WITH_PARAMS) {
     if (SkipParams (in) == XML_AUTO_CLOSE) {
       RemoveFromTokenList (&xmlParser);
       return TRUE;
     }
   }
   ReadXMLContent (in, tempParserString, &xmlParser . tokenState);
   if (xmlParser . tokenState != XML_TOKEN_CONTENT) {
     errorMessage = g_strdup_printf ("\nBad \'<tax:catalogNumber>\' token\nFile %s, line %ld\n", in -> name, in -> line);
     OnError ();
     return TRUE;
   }
   catalogName = g_strdup (tempParserString -> str);
 }
 else if ((!g_strcmp0 (tempParserString -> str, "tax:decimallatitude")) || (!g_strcmp0 (tempParserString -> str, "tax:decimallongitude"))) {
   actToken = GetPrevToken (&xmlParser);
   if (actToken == NULL) {
     errorMessage = g_strdup_printf ("\nUnexpected \'<%s>\' token\nFile %s, line %ld\n", tempParserString -> str, in -> name, in -> line);
     return FALSE;
   }
   if (g_strcmp0 (actToken -> str, "tax:taxonoccurrence")) {
     errorMessage = g_strdup_printf ("\nUnexpected \'<%s>\' token\nFile %s, line %ld\n", tempParserString -> str, in -> name, in -> line);
     return FALSE;
   }
   if (xmlParser . tokenState & XML_WITH_PARAMS) {
     if (SkipParams (in) == XML_AUTO_CLOSE) {
       RemoveFromTokenList (&xmlParser);
       return TRUE;
     }
   }
   actToken = (GString*) xmlParser . tokenStack -> data;
   ReadXMLContent (in, tempParserString, &xmlParser . tokenState);
   if (xmlParser . tokenState != XML_TOKEN_CONTENT) {
     errorMessage = g_strdup_printf ("\nBad \'<%s>\' token\nFile %s, line %ld\n", actToken -> str, in -> name, in -> line);
     return FALSE;
   }
   SetInStreamToString (cmdLine, tempParserString);
   if (GetCmdReal (&tmp) == TRUE) {
     if (!g_strcmp0 (actToken -> str, "tax:decimallatitude"))
       addLat = tmp;
     else if (!g_strcmp0 (actToken -> str, "tax:decimallongitude"))
       addLon = tmp;
   }
 }
 else if (!g_strcmp0 (tempParserString -> str, "tax2:namecomplete")) {
   if (xmlParser . tokenState & XML_WITH_PARAMS) {
     if (SkipParams (in) == XML_AUTO_CLOSE) {
       RemoveFromTokenList (&xmlParser);
       return TRUE;
     }
   }
   actToken = (GString*) xmlParser . tokenStack -> data;
   ReadXMLContent (in, tempParserString, &xmlParser . tokenState);
   if (xmlParser . tokenState != XML_TOKEN_CONTENT) {
     errorMessage = g_strdup_printf ("\nBad \'<%s>\' token\nFile %s, line %ld\n", actToken -> str, in -> name, in -> line);
     return FALSE;
   }
   termName = g_string_new (tempParserString -> str);
 }
 else if (!g_strcmp0 (tempParserString -> str, "tax:earliestdatecollected")) {
   actToken = GetPrevToken (&xmlParser);
   if (actToken == NULL) {
     errorMessage = g_strdup_printf ("\nUnexpected \'<%s>\' token\nFile %s, line %ld\n", tempParserString -> str, in -> name, in -> line);
     return FALSE;
   }
   if (g_strcmp0 (actToken -> str, "tax:taxonoccurrence")) {
     errorMessage = g_strdup_printf ("\nUnexpected \'<%s>\' token\nFile %s, line %ld\n", tempParserString -> str, in -> name, in -> line);
     return FALSE;
   }
   if (xmlParser . tokenState & XML_WITH_PARAMS) {
     if (SkipParams (in) == XML_AUTO_CLOSE) {
       RemoveFromTokenList (&xmlParser);
       return TRUE;
     }
   }
   ReadXMLContent (in, tempParserString, &xmlParser . tokenState);
   if (xmlParser . tokenState == XML_TOKEN_NOCONTENT) return TRUE;
   if (xmlParser . tokenState != XML_TOKEN_CONTENT) {
     errorMessage = g_strdup_printf ("\nBad \'<tax:catalogNumber>\' token\nFile %s, line %ld\n", in -> name, in -> line);
     OnError ();
     return TRUE;
   }
   sampleName = g_strdup (tempParserString -> str);
 }
 else
   return IgnoreOpenTag (&xmlParser);
 return TRUE;
}

SFLAG EndDarwinTag () {
 gchar* numStr;
 gchar* tmp;

 if (!g_strcmp0 (tempParserString -> str, "tax:taxonoccurrence")) {
   if ((addLon > -180.00001) && (addLon < 180.00001) && (addLat > -90.00001) && (addLat < 90.00001) && (termName != NULL)) {
     term = GetTermFromName (termName -> str);
     if (term != NULL) {
       actGeo = AddGeoRef (addLon, addLat, term -> node);
       actGeo -> name = AddSynonim (term, termName -> str);
       actGeo -> collec = g_strdup (collecName);
       actGeo -> catalog = catalogName;
       actGeo -> url = urlName;
       actGeo -> reference = referenceName;
       actGeo -> identifier = identifierName;
       actGeo -> sampleDate = sampleName;
       recordName = NULL;
       catalogName = NULL;
       urlName = NULL;
       referenceName = NULL;
       identifierName = NULL;
       sampleName = NULL;
     }
     else {
       g_string_append_printf (outBuffer, "\n<Folder>");
       g_string_append_printf (outBuffer, "\n\t<name>%s</name>", termName -> str);
       g_string_append (outBuffer, "\n\t<SpecimenInfo>");
       g_string_append_printf (outBuffer,"\n\t\t<name>%s</name>", termName -> str);
       if (collecName != NULL)
         g_string_append_printf (outBuffer, "\n\t\t<collection>%s</collection>", collecName);
       if (catalogName != NULL)
         g_string_append_printf (outBuffer, "\n\t\t<catalogCode>%s</catalogCode>", catalogName);
       if (urlName != NULL)
         g_string_append_printf (outBuffer, "\n\t\t<url>%s</url>", urlName);
       if (referenceName != NULL)
         g_string_append_printf (outBuffer, "\n\t\t<reference>%s</reference>", referenceName);
       if (identifierName != NULL)
         g_string_append_printf (outBuffer, "\n\t\t<identifiedBy>%s</identifiedBy>", identifierName);
       if (sampleName != NULL)
         g_string_append_printf (outBuffer, "\n\t\t<collectionDate>%s</collectionDate>", sampleName);
       if (collectorName != NULL)
         g_string_append_printf (outBuffer, "\n\t\t<collector>%s</collector>", collectorName);
       g_string_append (outBuffer, "\n\t\t<Point>");
       g_string_append (outBuffer, "\n\t\t\t<coordinates>");
       numStr = g_strdup_printf ("%.6f", addLon);
       CheckRealStr (numStr);
       g_string_append_printf (outBuffer, "%s,", numStr);
       g_free (numStr);
       numStr = g_strdup_printf ("%.6f", addLat);
       CheckRealStr (numStr);
       g_string_append (outBuffer, numStr);
       g_free (numStr);
       g_string_append (outBuffer, "</coordinates>");
       g_string_append (outBuffer, "\n\t\t</Point>\n\t</SpecimenInfo>");
       g_string_append (outBuffer, "\n</Folder>");
       unReadList = NameOnList (termName -> str, unReadList);
     }
   }
   tmp = g_strdup (collecName);
   FreeNames ();
   collecName = tmp;
   term = NULL;
   if (termName != NULL)
     g_string_free (termName, TRUE);
   termName = NULL;
   actGeo = NULL;
   addLon = 360.00;
   addLat = 360.00;
 }
 else if (!g_strcmp0 (tempParserString -> str, "dataresource")) {
   if (collecName != NULL)
     g_free (collecName);
   collecName = NULL;
 }
 return TRUE;
}

static GPtrArray* recArray = NULL;
static SFLAG validFile = FALSE;

SFLAG OpenVRXTag () {
 GString* actToken;
 SCOUNTER idVal;
 GList* nuRec;
 SFLAG onMarkup;

 progBar -> actBar1 = in -> actPos;
 UpdateOnCalculus ();
 if (!g_strcmp0 (tempParserString -> str, "vipresults")) {
   validFile = TRUE;
   recArray = NULL;
   actNode = NULL;
   nuTree = NULL;
   xmlParser . fileHeader = g_strdup (tempParserString -> str);
 }
 if (!g_strcmp0 (tempParserString -> str, "treeid")) {
   if (validFile == FALSE) {
     errorMessage = g_strdup_printf ("\nUnknown file format\nFile %s, line %ld\n", in -> name, in -> line);
     return FALSE;
   }
   actToken = GetPrevToken (&xmlParser);
   if (actToken == NULL) {
     errorMessage = g_strdup_printf ("\nUnexpected \'<treeID>\' token\nFile %s, line %ld\n", in -> name, in -> line);
     return FALSE;
   }
   if (g_strcmp0 (actToken -> str, "reconstruction")) {
     errorMessage = g_strdup_printf ("\nUnexpected \'<treeID>\' token\nFile %s, line %ld\n", in -> name, in -> line);
     IgnoreOpenTag (&xmlParser);
     return TRUE;
   }
   if (xmlParser . tokenState & XML_WITH_PARAMS) {
     if (SkipParams (in) == XML_AUTO_CLOSE) {
       RemoveFromTokenList (&xmlParser);
       return TRUE;
     }
   }
   ReadXMLContent (in, tempParserString, &xmlParser . tokenState);
   if (xmlParser . tokenState != XML_TOKEN_CONTENT) {
     errorMessage = g_strdup_printf ("\nBad \'<treeID>\' token: %s\nFile %s, line %ld\n", tempParserString -> str,
                                      in -> name, in -> line);
     OnError ();
     return TRUE;
   }
   SetInStreamToString (cmdLine, tempParserString);
   if (GetCmdNumber (&idVal) == TRUE)
     nuTree = GetTreeFromID (idVal);
   if (nuTree != NULL) {
     SetRec (nuTree -> recOR);
     nuRec = CopyActRec (nuTree);
     recArray = (GPtrArray*) nuRec -> data;
     SetRec (recArray);
     actNode = NULL;
     node = NULL;
   }
 }
 else if (!g_strcmp0 (tempParserString -> str, "nodeid")) {
   if (validFile == FALSE) {
     errorMessage = g_strdup_printf ("\nUnknown file format\nFile %s, line %ld\n", in -> name, in -> line);
     return FALSE;
   }
   actToken = GetPrevToken (&xmlParser);
   if (actToken == NULL) {
     errorMessage = g_strdup_printf ("\nUnexpected \'<nodeID>\' token\nFile %s, line %ld\n", in -> name, in -> line);
     return FALSE;
   }
   onMarkup = 0;
   if (!g_strcmp0 (actToken -> str, "distroelimination"))
     onMarkup = 1;
   else if (!g_strcmp0 (actToken -> str, "partialelimination"))
     onMarkup = 2;
   else {
     IgnoreOpenTag (&xmlParser);
     return TRUE;
   }
   if (xmlParser . tokenState & XML_WITH_PARAMS) {
     if (SkipParams (in) == XML_AUTO_CLOSE) {
       RemoveFromTokenList (&xmlParser);
       return TRUE;
     }
   }
   ReadXMLContent (in, tempParserString, &xmlParser . tokenState);
   if (xmlParser . tokenState != XML_TOKEN_CONTENT) {
     errorMessage = g_strdup_printf ("\nBad \'<nodeID>\' token: %s\nFile %s, line %ld\n", tempParserString -> str,
                                      in -> name, in -> line);
     OnError ();
     return TRUE;
   }
   SetInStreamToString (cmdLine, tempParserString);
   if (GetCmdNumber (&idVal) == TRUE) {
     node = GetNodeFromID (nuTree, idVal);
     if (node != NULL)
       actNode = node -> node;
   }
   if (actNode != NULL) {
     if (onMarkup == 1)
       SetNodeAsRemoved (actNode);
     else if (onMarkup == 2)
       SetNodeAsPartialRemov (actNode);
     actNode = NULL;
     node = NULL;
   }
   else {
     errorMessage = g_strdup_printf ("\nBad \'<nodeID>\' token: %s\nFile %s, line %ld\n", tempParserString -> str,
                                      in -> name, in -> line);
     OnError ();
   }
 }
 else {
   if (validFile == FALSE) {
     errorMessage = g_strdup_printf ("\nUnknown file format\nFile %s, line %ld\n", in -> name, in -> line);
     return FALSE;
   }
   return IgnoreOpenTag (&xmlParser);
 }
 return TRUE;
}

SFLAG EndVRXTag () {
 if (!g_strcmp0 (tempParserString -> str, "reconstruction")) {
   recArray = NULL;
   actNode = NULL;
   nuTree = NULL;
 }
 return TRUE;
}

SFLAG OnVRXError () {
 OnError ();
 FinishVRXFile ();
 return FALSE;
}

void FinishVRXFile () {
 recArray = NULL;
 actNode = NULL;
 nuTree = NULL;
 validFile = FALSE;
}

SFLAG FeedXYDFile () {
 SFLAG state;
 gchar* numStr;
 SCOUNTER numRecs;

 StartNuFeed ();
 for (;;) {
   progBar -> actBar1 = in -> actPos;
   UpdateOnCalculus ();
   if (ReadString (in, tempParserString) == EOF_REACHED) {
     errorMessage = g_strdup_printf ("Unexpected End of File\nExpecting \'xydata\' keyword\nFile: %s", in -> name);
     return OnFeedError ();
   }
   if (!g_strcmp0 (tempParserString -> str, "xydata")) break;
 }
 term = NULL;
 if (termName != NULL)
   g_string_free (termName, TRUE);
 termName = NULL;
 for (;;) {
   progBar -> actBar1 = in -> actPos;
   UpdateOnCalculus ();
   if (ReadString (in, tempParserString) == EOF_REACHED) break;
   if (g_strcmp0 (tempParserString -> str, "sp")) {
     errorMessage = g_strdup_printf ("Unknown expression %s\nExpecting \'sp\' keyword\nFile: %s, line: %ld",
                    tempParserString -> str, in -> name, in -> line);
     return OnFeedError ();
   }
   if (ReadInt (in, NULL) == BAD_IN_FORMAT) {
     errorMessage = g_strdup_printf ("Expecting number after \'sp\' keyword\nFile: %s, line: %ld", in -> name, in -> line);
     return OnFeedError ();
   }
   state = ReadBoundComment (in, tempParserString, '[', ']');
   if (state == EOF_REACHED) {
     errorMessage = g_strdup_printf ("Unclosed species name\nExpecting \']\'\nFile: %s", in -> name);
     return OnFeedError ();
   }
   if (state != BAD_IN_FORMAT) {
     termName = g_string_new (tempParserString -> str);
     term = GetTermFromName (termName -> str);
     if (term == NULL)
       unReadList = NameOnList (termName -> str, unReadList);
   }
   numRecs = 0;
   for (;;) {
     progBar -> actBar1 = in -> actPos;
     UpdateOnCalculus ();
     if (in -> state == EOF_REACHED) break;
     if ((in -> nextChar == 's') || (in -> nextChar == 'S')) break;
     addLat = addLon = 360.00;
     if (ReadReal (in, &addLon) == BAD_IN_FORMAT) {
       errorMessage = g_strdup_printf ("Expecting number\nFile: %s, line: %ld", in -> name, in -> line);
       return OnFeedError ();
     }
     if (in -> state == EOF_REACHED) {
       errorMessage = g_strdup_printf ("Unexpected End of File\nFile: %s", in -> name);
       return OnFeedError ();
     }
     if (ReadReal (in, &addLat) == BAD_IN_FORMAT) {
       errorMessage = g_strdup_printf ("Expecting number\nFile: %s, line: %ld", in -> name, in -> line);
       return OnFeedError ();
     }
     if ((addLon > -180.00001) && (addLon < 180.00001) && (addLat > -90.00001) && (addLat < 90.00001) && (termName != NULL)) {
       if (term != NULL) {
         actGeo = AddGeoRef (addLon, addLat, term -> node);
         actGeo -> name = AddSynonim (term, termName -> str);
       }
       else {
         if (numRecs == 0) {
           g_string_append_printf (outBuffer, "\n<Folder>");
           g_string_append_printf (outBuffer, "\n\t<name>%s</name>", termName -> str);
         }
         g_string_append (outBuffer, "\n\t<SpecimenInfo>");
         g_string_append_printf (outBuffer,"\n\t\t<name>%s</name>", termName -> str);
         g_string_append (outBuffer, "\n\t\t<Point>");
         g_string_append (outBuffer, "\n\t\t\t<coordinates>");
         numStr = g_strdup_printf ("%.6f", addLon);
         CheckRealStr (numStr);
         g_string_append_printf (outBuffer, "%s,", numStr);
         g_free (numStr);
         numStr = g_strdup_printf ("%.6f", addLat);
         CheckRealStr (numStr);
         g_string_append (outBuffer, numStr);
         g_free (numStr);
         g_string_append (outBuffer, "</coordinates>");
         g_string_append (outBuffer, "\n\t\t</Point>\n\t</SpecimenInfo>");
         ++ numRecs;
       }
     }
   }
   if ((numRecs > 0) && (term == NULL))
     g_string_append (outBuffer, "\n</Folder>");
   if (termName != NULL)
     g_string_free (termName, TRUE);
   term = NULL;
   termName = NULL;
 }
 return TRUE;
}

SFLAG FeedTABTable () {
 SINTEGER nameCount;
 SINTEGER collecCount;
 SINTEGER catalogCount;
 SINTEGER urlCount;
 SINTEGER referenceCount;
 SINTEGER identifierCount;
 SINTEGER sampleCount;
 SINTEGER collectorCount;
 SINTEGER latCount;
 SINTEGER lonCount;
 SCOUNTER i;
 SFLAG state;
 SREAL tmpNum;
 gchar* numStr;

 nameCount = collecCount = catalogCount = referenceCount = collectorCount = -1;
 urlCount = identifierCount = sampleCount = -1;
 latCount = lonCount = -1;

 /* Read headers */
 for (i = 0;; ++ i) {
   progBar -> actBar1 = in -> actPos;
   UpdateOnCalculus ();
   state = ReadStringUntil (in, tempParserString, '\t');
   if (state == EOF_REACHED) {
     errorMessage = g_strdup_printf ("Unknown file format\nFile: %s", in -> name);
     OnError ();
     return FALSE;
   }
   if (!g_strcmp0 (tempParserString -> str, "scientific name"))
     nameCount = i;
   else if (!g_strcmp0 (tempParserString -> str, "latitude"))
     latCount = i;
   else if (!g_strcmp0 (tempParserString -> str, "longitude"))
     lonCount = i;
   else if (!g_strcmp0 (tempParserString -> str, "dataset"))
     collecCount = i;
   else if ((!g_strcmp0 (tempParserString -> str, "catalogue no")) || (!g_strcmp0 (tempParserString -> str, "catalogue number")) ||
            (!g_strcmp0 (tempParserString -> str, "catalogue code")))
     catalogCount = i;
   else if ((!g_strcmp0 (tempParserString -> str, "gbif webservice url")) || (!g_strcmp0 (tempParserString -> str, "url")) ||
           (!g_strcmp0 (tempParserString -> str, "link")))
     urlCount = i;
   else if ((!g_strcmp0 (tempParserString -> str, "reference")) || (!g_strcmp0 (tempParserString -> str, "primary reference")))
     referenceCount = i;
   else if ((!g_strcmp0 (tempParserString -> str, "identifier")) || (!g_strcmp0 (tempParserString -> str, "authority")))
     identifierCount = i;
   else if (!g_strcmp0 (tempParserString -> str, "date collected"))
     sampleCount = i;
   else if ((!g_strcmp0 (tempParserString -> str, "collector")) || (!g_strcmp0 (tempParserString -> str, "collector name")) ||
           (!g_strcmp0 (tempParserString -> str, "collected by")))
     collectorCount = i;
   if (state == END_OF_IN_LINE) break;
 }
 if ((nameCount == -1) || (latCount == -1) || (lonCount == -1)) {
   errorMessage = g_strdup_printf ("Unknown file format\nFile: %s", in -> name);
   OnError ();
   return FALSE;
 }
 SETREADINGMODE (READ_AS_IS);
 StartNuFeed ();
 for (;;) {
   progBar -> actBar1 = in -> actPos;
   UpdateOnCalculus ();
   for (i = 0;; ++ i) {
     state = ReadStringUntil (in, tempParserString, '\t');
     if (state == EOF_REACHED) break;
     if (tempParserString -> len == 0) {
       if (state == END_OF_IN_LINE) break;
       continue;
     }
     if (i == nameCount) {
       termName = g_string_new (tempParserString -> str);
       term = GetTermFromName (termName -> str);
       if (term == NULL)
         unReadList = NameOnList (termName -> str, unReadList);
     }
     else if ((i == latCount) || (i == lonCount)) {
       SetInStreamToString (cmdLine, tempParserString);
       if (GetCmdReal (&tmpNum) != TRUE) {
         errorMessage = g_strdup_printf ("Expecting real value\nFile: %s, line: %ld, column: %ld", in -> name, in -> line, i);
         return OnFeedError ();
       }
       if (i == latCount)
         addLat = tmpNum;
       else if (i == lonCount)
         addLon = tmpNum;
     }
     else if (i == collecCount)
       collecName = g_strdup (tempParserString -> str);
     else if (i == catalogCount)
       catalogName = g_strdup (tempParserString -> str);
     else if (i == urlCount)
       urlName = g_strdup (tempParserString -> str);
     else if (i == referenceCount)
       referenceName = g_strdup (tempParserString -> str);
     else if (i == identifierCount)
       identifierName = g_strdup (tempParserString -> str);
     else if (i == sampleCount)
       sampleName = g_strdup (tempParserString -> str);
     else if (i == collectorCount)
       collectorName = g_strdup (tempParserString -> str);
     if (state == END_OF_IN_LINE) break;
   }
   if (state == EOF_REACHED) break;
   if ((addLon > -180.00001) && (addLon < 180.00001) && (addLat > -90.00001) && (addLat < 90.00001) && (termName != NULL)) {
     if (term != NULL) {
       actGeo = AddGeoRef (addLon, addLat, term -> node);
       actGeo -> name = AddSynonim (term, termName -> str);
       actGeo -> collec = g_strdup (collecName);
       actGeo -> catalog = catalogName;
       actGeo -> url = urlName;
       actGeo -> reference = referenceName;
       actGeo -> identifier = identifierName;
       actGeo -> sampleDate = sampleName;
       actGeo -> collector = collectorName;
       recordName = NULL;
       catalogName = NULL;
       urlName = NULL;
       referenceName = NULL;
       identifierName = NULL;
       sampleName = NULL;
       collectorName = NULL;
     }
     else {
       g_string_append_printf (outBuffer, "\n<Folder>");
       g_string_append_printf (outBuffer, "\n\t<name>%s</name>", termName -> str);
       g_string_append (outBuffer, "\n\t<SpecimenInfo>");
       g_string_append_printf (outBuffer,"\n\t\t<name>%s</name>", termName -> str);
       if (collecName != NULL)
         g_string_append_printf (outBuffer, "\n\t\t<collection>%s</collection>", collecName);
       if (catalogName != NULL)
         g_string_append_printf (outBuffer, "\n\t\t<catalogCode>%s</catalogCode>", catalogName);
       if (urlName != NULL)
         g_string_append_printf (outBuffer, "\n\t\t<url>%s</url>", urlName);
       if (referenceName != NULL)
         g_string_append_printf (outBuffer, "\n\t\t<reference>%s</reference>", referenceName);
       if (identifierName != NULL)
         g_string_append_printf (outBuffer, "\n\t\t<identifiedBy>%s</identifiedBy>", identifierName);
       if (sampleName != NULL)
         g_string_append_printf (outBuffer, "\n\t\t<collectionDate>%s</collectionDate>", sampleName);
       if (collectorName != NULL)
         g_string_append_printf (outBuffer, "\n\t\t<collector>%s</collector>", collectorName);
       g_string_append (outBuffer, "\n\t\t<Point>");
       g_string_append (outBuffer, "\n\t\t\t<coordinates>");
       numStr = g_strdup_printf ("%.6f", addLon);
       CheckRealStr (numStr);
       g_string_append_printf (outBuffer, "%s,", numStr);
       g_free (numStr);
       numStr = g_strdup_printf ("%.6f", addLat);
       CheckRealStr (numStr);
       g_string_append (outBuffer, numStr);
       g_free (numStr);
       g_string_append (outBuffer, "</coordinates>");
       g_string_append (outBuffer, "\n\t\t</Point>\n\t</SpecimenInfo>");
       g_string_append (outBuffer, "\n</Folder>");
     }
   }
   if (termName != NULL)
     g_string_free (termName, TRUE);
   term = NULL;
   termName = NULL;
   FreeNames ();
   addLon = addLat = 360.00;
 }
 return TRUE;
}

void StartNuFeed () {
 term = NULL;
 unReadList = NULL;
 termName = NULL;
 actGeo = NULL;
 FreeNames ();
 outBuffer = g_string_sized_new (1024);
 g_string_append (outBuffer, "<?xml version=\"1.0\"?>");
 g_string_append_printf (outBuffer, "\n<!-- Unreaded records from file %s -->", in -> name);
 g_string_append (outBuffer, "\n\n<Vip>");
 addLon = 360.00;
 addLat = 360.00;
}

void FreeNames () {
 if (collecName != NULL)
   g_free (collecName);
 if (catalogName != NULL)
   g_free (catalogName);
 if (urlName != NULL)
   g_free (urlName);
 if (referenceName != NULL)
   g_free (referenceName);
 if (identifierName != NULL)
   g_free (identifierName);
 if (sampleName != NULL)
   g_free (sampleName);
 recordName = NULL;
 collecName = NULL;
 catalogName = NULL;
 urlName = NULL;
 referenceName = NULL;
 identifierName = NULL;
 sampleName = NULL;
 collectorName = NULL;
}

void FinishUnRead () {
 GString* unReadBuffer;
 GList* nav;
 GString* name;

 if (unReadList != NULL) {
   g_string_append (outBuffer, "\n\n</Vip>\n");
   WriteOutLog ("unfeed.xml", outBuffer);
   unReadBuffer = g_string_sized_new (1024);
   g_string_append (unReadBuffer, "<?xml version=\"1.0\"?>");
   g_string_append (unReadBuffer, "\n\n<!-- Unmatched names -->\n");
   g_string_append (unReadBuffer, "\n\n<Vip>\n");
   for (nav = unReadList; nav != NULL; nav = g_list_next (nav)) {
     name = (GString*) nav -> data;
     g_string_append_printf (unReadBuffer, "\n<Folder>\n\t<name>%s</name>", name -> str);
     g_string_append_printf (unReadBuffer, "\n\t<synonym>%s</synonym>", name -> str);
     g_string_append (unReadBuffer, "\n</Folder>");
   }
   g_string_append (unReadBuffer, "\n\n</Vip>\n");
   g_string_append (unReadBuffer, "\n");
   WriteOutLog ("unmatch.xml", unReadBuffer);
   g_string_free (unReadBuffer, TRUE);
   CleanNameList (unReadList);
 }
 g_string_free (outBuffer, TRUE);
 if (termName != NULL)
   g_string_free (termName, TRUE);
}

void CleanNameList (GList* toClean) {
 GList* nav;
 for (nav = toClean; nav != NULL; nav = g_list_next (nav))
   g_string_free (nav -> data, TRUE);
 g_list_free (toClean);
}

SFLAG ReadRealTuple (INSTREAM* from, SREAL* r1, SREAL* r2) {
 if ((!g_ascii_isdigit (from -> nextChar)) && (from -> nextChar != '-')) return FALSE;
 ReadReal (from, r1);
 if (from -> nextChar == ',')
   ReadChar (from, NULL);
 SkipSpaces (from);
 if ((!g_ascii_isdigit (from -> nextChar)) && (from -> nextChar != '-')) return FALSE;
 ReadReal (from, r2);
 return TRUE;
}

void SetCommandLine (gchar* text) {
 if (cmdLine == NULL)
   cmdLine = CreateInStream ();
 else
   ResetInStream (cmdLine);
 if (tempParserString == NULL)
   tempParserString = g_string_new (VOIDSTRING);
 g_string_printf (tempParserString, text);
 SetInStreamToString (cmdLine, tempParserString);
}

SFLAG GetCmdNumber (SINTEGER* dest) {
 if (cmdLine -> nextChar == 0) return FALSE;
 SkipSpaces (cmdLine);
 if ((!g_ascii_isdigit (cmdLine -> nextChar)) && (cmdLine -> nextChar != '-')) return FALSE;
 ReadInt (cmdLine, dest);
 return TRUE;
}

SFLAG GetCmdReal (SREAL* dest) {
 if (cmdLine -> nextChar == 0) return FALSE;
 SkipSpaces (cmdLine);
 if ((!g_ascii_isdigit (cmdLine -> nextChar)) && (cmdLine -> nextChar != '-')) return FALSE;
 ReadReal (cmdLine, dest);
 return TRUE;
}

SFLAG IsXYDFile () {
 SkipSpaces (in);
 if (ReadString (in, tempParserString) == EOF_REACHED) {
   in -> line = 0;
   in -> actPos = 0;
   SkipSpaces (in);
   return FALSE;
 }
 if (!g_strcmp0 (tempParserString -> str, "spp")) {
   if (ReadInt (in, NULL) == BAD_IN_FORMAT) {
     in -> line = 0;
     in -> actPos = 0;
     SkipSpaces (in);
     return FALSE;
   }
   return TRUE;
 }
 in -> line = 0;
 in -> actPos = 0;
 SkipSpaces (in);
 return FALSE;
}
